package Hxw3DEngine.utils
{
	
	
	import flash.display.*;
	import flash.display3D.textures.CubeTexture;
	import flash.display3D.textures.Texture;
	import flash.geom.Matrix;
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	import flash.utils.*;
	import Hxw3DEngine.core.Resource.geometry.ResourceGeometry;
	
	public class Stage3dUtils
	{
		/**
		 *嵌入的图片直接转成bitmapdata 
		 * @param data
		 * @return 
		 * 
		 */		
		public static function bitmapData(data:*):BitmapData
		{
			if(data as BitmapData){
				return data;
			}
			
			if (data is Class) {
				try {
					data = new data;
				} catch (bitmapError:ArgumentError) {
					data = new data(0, 0);
				}
			}
			
			if (data is DisplayObject) {
				var ds:DisplayObject = data as DisplayObject;
				var bmd:BitmapData = new BitmapData(ds.width, ds.height, true, 0x00FFFFFF);
				var mat:Matrix = ds.transform.matrix.clone();
				mat.tx = 0;
				mat.ty = 0;
				bmd.draw(ds, mat, ds.transform.colorTransform, ds.blendMode, bmd.rect, true);
				return bmd;
			}
			return null;
		}
		
		/**
		 *上传mipmap 
		 * @param texture
		 * @param bmd
		 * 
		 */		
		public static function uploadMipMap(texture:Texture,bmd:BitmapData):void{
			var ws:int = bmd.width;
			var hs:int = bmd.height;
			var level:int = 0;
			var tmp:BitmapData;
			var transform:Matrix = new Matrix();
			tmp = new BitmapData(ws, hs, true, 0x00000000);
			while ( ws >= 1 && hs >= 1 )
			{ 
				tmp.draw(bmd, transform, null, null, null, true); 
				texture.uploadFromBitmapData(tmp, level);
				transform.scale(0.5, 0.5);
				level++;
				ws >>= 1;
				hs >>= 1;
				if (hs && ws) 
				{
					tmp.dispose();
					tmp = new BitmapData(ws, hs, true, 0x00000000);
				}
			}
			tmp.dispose();
		}
		
		public static function uploadCubeMipMap(texture:CubeTexture,bmd:BitmapData,side:int):void{
			var ws:int = bmd.width;
			var hs:int = bmd.height;
			var level:int = 0;
			var tmp:BitmapData;
			var transform:Matrix = new Matrix();
			tmp = new BitmapData(ws, hs, true, 0x00000000);
			while ( ws >= 1 && hs >= 1 )
			{ 
				tmp.draw(bmd, transform, null, null, null, true); 
				texture.uploadFromBitmapData(tmp,side,level);
				transform.scale(0.5, 0.5);
				level++;
				ws >>= 1;
				hs >>= 1;
				if (hs && ws) 
				{
					tmp.dispose();
					tmp = new BitmapData(ws, hs, true, 0x00000000);
				}
			}
			tmp.dispose();
		}
		
		public static const RAW_DATA_CONTAINER:Vector.<Number> = new Vector.<Number>(16);
		public static const CALCULATION_VECTOR3D:Vector3D = new Vector3D();
		public static function transformVector(matrix:Matrix3D, vector:Vector3D, result:Vector3D = null):Vector3D {
			if (!result) result = new Vector3D();
			var raw:Vector.<Number> = RAW_DATA_CONTAINER;
			matrix.copyRawDataTo(raw);
			var a:Number = raw[0];
			var e:Number = raw[1];
			var i:Number = raw[2];
			var m:Number = raw[3];
			var b:Number = raw[4];
			var f:Number = raw[5];
			var j:Number = raw[6];
			var n:Number = raw[7];
			var c:Number = raw[8];
			var g:Number = raw[9];
			var k:Number = raw[10];
			var o:Number = raw[11];
			var d:Number = raw[12];
			var h:Number = raw[13];
			var l:Number = raw[14];
			var p:Number = raw[15];
			
			var x:Number = vector.x;
			var y:Number = vector.y;
			var z:Number = vector.z;
			result.x = a * x + b * y + c * z + d;
			result.y = e * x + f * y + g * z + h;
			result.z = i * x + j * y + k * z + l;
			result.w = m * x + n * y + o * z + p;
			return result;
		}
		
		
		public static function toByteArray(data:*):ByteArray
		{
			if (data is Class)
				data = new data();
			
			if (data is ByteArray)
				return data;
			else
				return null;
		}
		
		/**
		 * Returns a object as String, if possible.
		 * 
		 * @param data The object to return as String
		 * @param length The length of the returned String
		 * 
		 * @return The String or null
		 *
		 */
		public static function toString(data:*, length:uint = 0):String
		{
			var ba:ByteArray;
			
			length ||= uint.MAX_VALUE;
			
			if (data is String)
				return String(data).substr(0, length);
			
			ba = toByteArray(data);
			if (ba) {
				ba.position = 0;
				return ba.readUTFBytes(Math.min(ba.bytesAvailable, length));
			}
			
			return null;
		}
		
		//根据类型获得注释
		public static function getDesByType(type:int):String {
			var des:String;
			switch(type) {
				case ResourceGeometry.POSITION:
					des = "顶点V";
					break;
				case ResourceGeometry.UV0:
					des = "UV0V";
					break;
					case ResourceGeometry.UV1:
					des = "UV1V";
					break;
					case ResourceGeometry.UV2:
					des = "UV2V";
					break;
					case ResourceGeometry.UV3:
					des = "UV3V";
					break;
					case ResourceGeometry.NORMAL:
					des = "法线V";
					break;
					case ResourceGeometry.TANGENT:
					des = "切线V";
					break;
					case ResourceGeometry.RGBA:
					des = "RGBAV";
					break;
					case ResourceGeometry.SKIN_INDICES:
					des = "骨骼索引V";
					break;
					case ResourceGeometry.SKIN_WEIGHTS:
					des = "骨骼权重V";
					break;
					case ResourceGeometry.BONE_0_1:
					des = "权重0-1V";
					break;
					case ResourceGeometry.BONE_2_3:
					des = "权重2-3V";
					break;
					case ResourceGeometry.RGB:
					des = "RGBV";
					break;
					case ResourceGeometry.CUSTOM1:
					des = "自定义1V";
					break;
					case ResourceGeometry.CUSTOM2:
					des = "自定义2V";
					break;
					case ResourceGeometry.CUSTOM3:
					des = "自定义3V";
					break;
					case ResourceGeometry.CUSTOM4:
					des = "自定义4V";
					break;
			}
			
			return des;
		}
		
		private static var resultCode:String;
		//生成GPU代码注释
		public static function BuildDes(...ary):String {
			resultCode = "\n    ";
			for (var i:int = 0; i < ary.length; i++) {
				var obj:Object = ary[i];
				if (i != 0) resultCode += ",";
				resultCode += (obj is String?obj:obj.des);
			}
			return resultCode;
		}
		
		
		
	}
}
